package be.kuleuven.cs.mop.domain.model.impl;

import be.kuleuven.cs.mop.domain.exceptions.BusinessRuleThreeViolationExceptionDeadlineExpired;
import be.kuleuven.cs.mop.domain.exceptions.BusinessRuleTwoViolationExceptionDependantTasks;
import be.kuleuven.cs.mop.domain.exceptions.BusinessRuleTwoViolationExceptionTask;
import be.kuleuven.cs.mop.domain.model.TaskStatus;




public class TaskStateFailed extends TaskState {
	
	protected TaskStateFailed(final TaskImpl task) {
		super(task);
	}
	
	/**
	 * Business rule 3 is already always enforced when this state is failed, so check is not necessary when time changes
	 */
	protected void enforceBusinessRule3(Clock time) {
		// Ignored
	}
	
	@Override
	public void setFailedSafely() {
		// Ignored
	}
	
	/**
	 * Changes state from failed to Unfinished
	 * Checks the first part of business rule 2, since this is the only place where this violation can happen
	 * 
	 * @throws BusinessRuleTwoViolationExceptionTask - Thrown when one of the depending tasks has status failed
	 * @throws BusinessRuleTwoViolationExceptionDependantTasks - {@link TaskState#setUnfinishedSafely()}
	 * @throws BusinessRuleThreeViolationExceptionDeadlineExpired - {@link BusinessRuleThreeViolationExceptionDeadlineExpired#DEFAULT_MESSAGE}
	 */
	@Override
	public void setUnfinishedSafely() throws BusinessRuleTwoViolationExceptionTask, BusinessRuleTwoViolationExceptionDependantTasks, BusinessRuleThreeViolationExceptionDeadlineExpired {
		checkBusinessRule2DependingTasksFailed();
		super.setUnfinishedSafely();
	}
	
	/**
	 * Checks business rule 2 (first part) when changing this state to unfinished
	 * This check should also be done when migrating to Successful, but it's redundant because the general check in setSuccessFul safely already checks this implicitly
	 * 
	 * @throws BusinessRuleTwoViolationExceptionTask - Thrown when one of the depending tasks has status failed
	 */
	private void checkBusinessRule2DependingTasksFailed() throws BusinessRuleTwoViolationExceptionTask {
		for (final TaskImpl dependency : getTask().getDependencies())
			if (dependency.getState().isFailed())
				throw new BusinessRuleTwoViolationExceptionTask(dependency);
	}
	
	@Override
	public boolean isFailed() { return true; }
	
	@Override
	public TaskStatus toStatus() { return TaskStatus.FAILED; }
	
}